
#import "hyperlink_button_cell.h"

@interface HyperlinkButtonCell (Private)
- (NSDictionary*)linkAttributres;
- (void)customizeButtonCell;
@end

@implementation HyperlinkButtonCell
@dynamic textColor;
@dynamic textHoverColor;
@dynamic hasUnderLine;

+ (NSColor*)defaultTextColor {
  return [NSColor blueColor];
}

// Designated initializer.
- (id)init {
    if ((self = [super init])) {
        [self customizeButtonCell];
        [self setTextColor:[HyperlinkButtonCell defaultTextColor]];
        [self setTextHoverColor:[HyperlinkButtonCell defaultTextColor]];      
        isMouseIn_ = NO;
        hasUnderLine_ = YES;
    }
    return self;
}

// Initializer called when the cell is loaded from the NIB.
- (id)initWithCoder:(NSCoder*)aDecoder {
    if ((self = [super initWithCoder:aDecoder])) {
        [self customizeButtonCell];
        [self setTextColor:[HyperlinkButtonCell defaultTextColor]];
        [self setTextHoverColor:[HyperlinkButtonCell defaultTextColor]];   
        isMouseIn_ = NO;
        hasUnderLine_ = YES;
    }
    return self;
}

// Initializer for code-based creation.
- (id)initTextCell:(NSString*)title {
    if ((self = [super initTextCell:title])) {
        [self customizeButtonCell];
    }
    return self;
}

// Because an NSButtonCell has multiple initializers, this method performs the
// common cell customization code.
- (void)customizeButtonCell {
    [self setBordered:NO];

    CGFloat fontSize = [NSFont systemFontSizeForControlSize:[self controlSize]];
    NSFont* font = [NSFont controlContentFontOfSize:fontSize];
    [self setFont:font];

    // Do not change button appearance when we are pushed.
    [self setHighlightsBy:NSNoCellMask];

    // We need to set this so that we can override |-mouseEntered:| and
    // |-mouseExited:| to change the cursor style on hover states.
    [self setShowsBorderOnlyWhileMouseInside:YES];
}

- (void)setControlSize:(NSControlSize)size {
    [super setControlSize:size];
    [self customizeButtonCell];  // recompute |font|.
}

// Creates the NSDictionary of attributes for the attributed string.
- (NSDictionary*)linkAttributes {
    int underlineMask = NSUnderlinePatternSolid;
    if ([self hasUnderLine]) {
        underlineMask |= NSUnderlineStyleSingle;
    }

    NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    [paragraphStyle setAlignment:[self alignment]];

    return [NSDictionary dictionaryWithObjectsAndKeys:
      isMouseIn_ ? [self textHoverColor] : [self textColor], NSForegroundColorAttributeName,
      [NSNumber numberWithInt:underlineMask], NSUnderlineStyleAttributeName,
      [self font], NSFontAttributeName,
      [NSCursor pointingHandCursor], NSCursorAttributeName,
      paragraphStyle, NSParagraphStyleAttributeName,
      nil
    ];
}

// Override the drawing for the cell so that the custom style attributes
// can always be applied and so that ellipses will appear when appropriate.
- (NSRect)drawTitle:(NSAttributedString*)title
          withFrame:(NSRect)frame
             inView:(NSView*)controlView {
    NSDictionary* linkAttributes = [self linkAttributes];
    NSString* plainTitle = [title string];
    [plainTitle drawWithRect:frame
                   options:(NSStringDrawingUsesLineFragmentOrigin |
                            NSStringDrawingTruncatesLastVisibleLine)
                attributes:linkAttributes];
    return frame;
}

// Override the default behavior to draw the border. Instead, change the cursor.
- (void)mouseEntered:(NSEvent*)event {
    [[NSCursor pointingHandCursor] push];
    isMouseIn_ = YES;
    [[self controlView]setNeedsDisplay: YES];
}

- (void)mouseExited:(NSEvent*)event {
    [NSCursor pop];
    isMouseIn_ = NO;
    [[self controlView]setNeedsDisplay: YES];
}

// Setters and getters.
- (NSColor*)textColor {
    return textColor_;
}

- (void)setTextColor:(NSColor*)color {
    if (textColor_ != color) {
        [textColor_ release];
        textColor_ = nil;
        textColor_ = [color retain];
    }
}

// Setters and getters.
- (NSColor*)textHoverColor {
    return textHoverColor_;
}

- (void)setTextHoverColor:(NSColor*)color {
    if (textHoverColor_ != color) {
        [textHoverColor_ release];
        textHoverColor_ = nil;
        textHoverColor_ = [color retain];
    }
}

// Setters and getters.
- (BOOL)hasUnderLine {
    return hasUnderLine_;
}

- (void)setHasUnderLine:(BOOL)hasUnderLine {
    hasUnderLine_ = hasUnderLine;
}

// Override so that |-sizeToFit| works better with this type of cell.
- (NSSize)cellSize {
    NSSize size = [super cellSize];
    size.width += 2;
    return size;
}

@end
